# coding=utf-8
'''
Created on 2016-03-26

@author: Genji
'''

import sys
import pygame
import random

COLORS_ARRAY = [(0, 0, 0), (255, 0, 0), (255, 153, 0), (255, 255, 0), (0, 255, 0), (0, 255, 255), (0, 0, 255), (153, 0, 255), (255, 0, 255)]
STATUS_NOTHING = 2
STATUS_BLOCK = 0
STATUS_SELECTED = 1
STATUS_INIT = -1
STATUS_RUNNING = -2
STATUS_LOST = -3

main_array = [[0 for col in range(16)] for row in range(16)]
current_score = 0
current_status = STATUS_INIT
is_removing = False
linkable_list = []

def find_linkable(x, y):
    global linkable_list
    linkable_list.append((x, y))
    if x > 0 and main_array[x][y] == main_array[x - 1][y] and (x - 1, y) not in linkable_list:
        find_linkable(x - 1, y)
    if y < 15 and main_array[x][y] == main_array[x][y + 1] and (x, y + 1) not in linkable_list:
        find_linkable(x, y + 1)
    if x < 15 and main_array[x][y] == main_array[x + 1][y] and (x + 1, y) not in linkable_list:
        find_linkable(x + 1, y)
    if y > 0 and main_array[x][y] == main_array[x][y - 1] and (x, y - 1) not in linkable_list:
        find_linkable(x, y - 1)

def start_game():
    global current_score
    global current_status
    current_score = 0
    current_status = STATUS_RUNNING
    for i in range(0, 16):
        for j in range(0, 16):
            main_array[i][j] = random.randint(1, 8)

pygame.init()
screen = pygame.display.set_mode((528, 560), 0, 32)
pygame.display.set_caption("Simple Endless Blocks")
global_font = pygame.font.SysFont(None, 32)
init_text_surface = global_font.render("Game ready.Press ENTER to start.", True, (255, 255, 255))
lost_text_surface = global_font.render("You lost.Press ENTER to restart.", True, (255, 255, 255))

loop_flag = True
while loop_flag:
    if current_status == STATUS_INIT:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                loop_flag = False
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_RETURN:
                    start_game()
        
        screen.fill((0, 0, 0))
        x = init_text_surface.get_width() // 2
        y = init_text_surface.get_height() // 2
        screen.blit(init_text_surface, (264 - x, 280 - y))
        pygame.display.update()
                
    elif current_status == STATUS_RUNNING:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                loop_flag = False
            elif event.type == pygame.MOUSEBUTTONDOWN:
                if not is_removing:
                    x, y = pygame.mouse.get_pos()
                    if x >= 8 and x <= 520 and y >= 8 and y <= 520:
                        x -= 8
                        y -= 8
                        x = x // 32
                        y = y // 32
                        status = main_array[x][y] // 10
                        if status == STATUS_BLOCK:
                            flag = False
                            for i in range(0, 16):
                                for j in range(0, 16):
                                    if main_array[i][j] // 10 == STATUS_SELECTED:
                                        main_array[i][j] = (STATUS_BLOCK * 10) + (main_array[i][j] % 10)
                                        flag = True
                                        
                            if not flag:
                                linkable_list = []
                                find_linkable(x, y)
                                if len(linkable_list) > 1:
                                    for pos in linkable_list:
                                        main_array[pos[0]][pos[1]] = (STATUS_SELECTED * 10) + (main_array[x][y] % 10)
                        
                        elif status == STATUS_SELECTED:
                            linkable_list = []
                            find_linkable(x, y)
                            length = len(linkable_list)
                            if length > 1:
                                current_score += length * length
                                for pos in linkable_list:
                                    main_array[pos[0]][pos[1]] = (STATUS_NOTHING * 10) + (main_array[x][y] % 10)
                
        screen.fill((0, 0, 0))
        for i in range(0, 16):
            for j in range(0, 16):
                status = main_array[i][j] // 10
                if status == STATUS_BLOCK:
                    pygame.draw.rect(screen, COLORS_ARRAY[main_array[i][j] % 10], [8 + 32 * i, 8 + 32 * j, 30, 30])
                elif status == STATUS_SELECTED:
                    pygame.draw.circle(screen, COLORS_ARRAY[main_array[i][j] % 10], (23 + 32 * i, 23 + 32 * j), 15)
                        
        for i in range(0, 16):
            for j in range(0, 16):
                if (main_array[i][15 - j] // 10) == STATUS_NOTHING:
                    for k in range(0, 15 - j):
                        if main_array[i][15 - j - k] // 10 != STATUS_NOTHING:
                            main_array[i][15 - j] = main_array[i][15 - j - k]
                            main_array[i][15 - j - k] = (STATUS_NOTHING * 10) + (main_array[i][15 - j - k] % 10)
                            break
                if (main_array[i][15 - j] // 10) == STATUS_NOTHING:
                    main_array[i][15 - j] = random.randint(1, 8)
        
        can_remove = False            
        for i in range(1, 15):
            for j in range(1, 15):
                if main_array[i][j] == main_array[i + 1][j] or main_array[i][j] == main_array[i - 1][j] or main_array[i][j] == main_array[i][j + 1] or main_array[i][j] == main_array[i][j - 1]:
                    can_remove = True
        if main_array[0][0] == main_array[0][1] or main_array[0][0] == main_array[1][0] or main_array[0][15] == main_array[0][14] or main_array[0][15] == main_array[1][15] or main_array[15][0] == main_array[15][1] or main_array[15][0] == main_array[14][0] or main_array[15][15] == main_array[14][15] or main_array[15][15] == main_array[15][14]:
            can_remove = True
        if not can_remove:
            current_status = STATUS_LOST
                    
        score_text_surface = global_font.render("SCORE:" + '%d' % current_score, True, (255, 255, 255))
        screen.blit(score_text_surface, (8, 528))        
        pygame.display.update()
                
    elif current_status == STATUS_LOST:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                loop_flag = False
            elif event.type == pygame.KEYDOWN:
                if event.key == pygame.K_RETURN:
                    start_game()
                
        screen.fill((0, 0, 0))
        x = lost_text_surface.get_width() // 2
        y = lost_text_surface.get_height() // 2
        screen.blit(lost_text_surface, (264 - x, 280 - y))
        pygame.display.update()

sys.exit()    
